﻿#include "CameraPC_Qt6.h"
#include <QCameraDevice>
#include <QVideoSink>
#include <QMediaDevices>
#include <QMediaCaptureSession>
#include <QList>

namespace Qly {


CameraPC_Qt6::CameraPC_Qt6(QObject *parent)
    :Qly::IndustryCamera(parent)
{
    m_cameraImageProcessing = new CameraPCImageProcessing;
    m_dialog = new DialogCameraSetup(this);
    m_pSession = new QMediaCaptureSession(this);
}


void CameraPC_Qt6::setVideoFrame(const QVideoFrame &frame)
{
//    qDebug() << frame.pixelFormat();
    AVPixelFormat format = AV_PIX_FMT_NONE;
    int stride = frame.bytesPerLine(0);

    //qDebug() << "CameraPCVideoSurface::setVideoFrame";
    //qDebug() << frame.pixelFormat();
    switch (frame.pixelFormat())
    {
    // case QVideoFrameFormat::Format_RGB24:
    //     format = AV_PIX_FMT_RGB24;
    //     //emit camera->RGB24ImageChanged(frame.bits(), frame.size());
    //     break;
    case QVideoFrameFormat::Format_XRGB8888:
    case QVideoFrameFormat::Format_ARGB8888:
        format = AV_PIX_FMT_BGRA;
        //emit camera->RGB32ImageChanged(frame.bits(), frame.size());
        break;
    case QVideoFrameFormat::Format_Y8:
        format = AV_PIX_FMT_GRAY8;
        //camera->Bayer8ImageChanged(frame.bits(), frame.size());
        break;
    case QVideoFrameFormat::Format_YUYV:
        format = AV_PIX_FMT_YUYV422;
        //camera->YUYVImageChanged(frame.bits(), frame.size());
        break;
    case QVideoFrameFormat::Format_UYVY:
        format = AV_PIX_FMT_UYVY422;
        //camera->UYVYImageChanged(frame.bits(), frame.size());
        break;
    default:
        format = AV_PIX_FMT_NONE;
        break;
    }
    VideoFrame videoframe((uint8_t *)frame.bits(0), stride, frame.size(), format);
    videoframe.setExtraInfo(m_imageCount ++, QDateTime::currentDateTime());
    emit videoFrameReady(videoframe);
    //emit camera->ImageDataChanged(frame.bits(), stride, frame.size(), format);
}


void CameraPC_Qt6::on_videoFrame(const QVideoFrame &frame)
{
    //qDebug() << "in CameraPC_Qt6::on_videoFrame()";
    if(frame.isMapped())
    {
        setVideoFrame(frame);
    }
    else
    {
        QVideoFrame f = frame;
        f.map(QVideoFrame::ReadOnly);
        setVideoFrame(f);
    }
}

bool CameraPC_Qt6::showVCDPropertyPage()
{
    if(!m_pQCamera) return false;
    //m_dialog->m_pQCamera = m_pQCamera;
    m_dialog->initNodeInfo();
    m_dialog->show();
    return true;
}

bool CameraPC_Qt6::isLive()
{
    return (m_pQCamera->isActive());
}

bool CameraPC_Qt6::setResolution(QSize size)
{
    // if(m_pQCamera)
    // {
    //     //m_pQCamera->load();
    //     QCameraViewfinderSettings  settings = m_pQCamera->viewfinderSettings();
    //     settings.setResolution(size);
    //     m_pQCamera->setViewfinderSettings(settings);
    //     return true;
    // }
    return false;
}

bool CameraPC_Qt6::openCameraByInfo(QCameraDevice cameraDevice)
{
    qDebug() << "CameraPC::openCameraByInfo(QCameraInfo info)";
    if(m_pQCamera)
    {
        delete m_pQCamera;
    }
    if(!cameraDevice.isNull())
    {
        m_pQCamera = new QCamera(cameraDevice);
        CameraPCImageProcessing * p = static_cast<CameraPCImageProcessing *>(m_cameraImageProcessing);
        p->m_pQCamera = m_pQCamera;
        if(m_surface)
        {
            delete m_surface;
        }
        m_surface = new QVideoSink(this);
        connect(m_surface, &QVideoSink::videoFrameChanged, this, &CameraPC_Qt6::on_videoFrame);
        m_pSession->setVideoSink(m_surface);
        m_pSession->setCamera(m_pQCamera);


        m_DeviceModelName = cameraDevice.description();
        return true;
    }
    return false;
}

bool CameraPC_Qt6::openDefaultCamera()
{
    if(m_pQCamera)
    {
        delete m_pQCamera;
    }
    QCameraDevice cameraDevice = QMediaDevices::defaultVideoInput();
    //qDebug() << info;//
    //qDebug() << "CameraPC::openDefaultCamera() : " << info.deviceName();
    return openCameraByInfo(cameraDevice);
}

bool CameraPC_Qt6::openCameraByName(QString name)
{

    const QList<QCameraDevice> cameras = QMediaDevices::videoInputs();
    for (const QCameraDevice &cameraDevice : cameras) {
        if (cameraDevice.description() == name)
            return openCameraByInfo(cameraDevice);
    }
      return false;
}

bool CameraPC_Qt6::setExposureTime(double us)
{
    if(m_pQCamera)
    {
        m_pQCamera->setManualExposureTime(us / 1000.0 / 1000.0);
        qDebug() << "setManualExposureTime = " << us / 1000.0 / 1000.0;
        return true;
    }
    return false;
}

bool CameraPC_Qt6::exposureTimeMode(AutoExposureMode &mode)
{
    if(m_pQCamera)
    {
        QCamera::ExposureMode m = m_pQCamera->exposureMode();

        switch (m) {
        case QCamera::ExposureAuto:
            mode = IndustryCamera::CONTINUOUS;
            break;
        case QCamera::ExposureManual:
            mode = IndustryCamera::OFF;
            break;
        default:
            mode = IndustryCamera::OFF;
            break;
        }
        return true;
    }
    return false;
}

bool CameraPC_Qt6::setExposureTimeMode(AutoExposureMode mode)
{
    if(m_pQCamera)
    {
        switch (mode) {
        case IndustryCamera::OFF:
            m_pQCamera->setExposureMode(QCamera::ExposureManual);
            qDebug() << "setExposureMode(QCamera::ExposureManual);";
            break;
        case IndustryCamera::CONTINUOUS:
            m_pQCamera->setExposureMode(QCamera::ExposureAuto);
            qDebug() << "setExposureMode(QCamera::ExposureAuto);";
            break;
        case IndustryCamera::ONCE:
            //exp->setExposureMode(QCamera::ExposureAuto);
            break;
        }
        return true;
    }
    return false;
}

bool CameraPC_Qt6::exposureTime(double &us)
{
    if(m_pQCamera)
    {
        us = m_pQCamera->exposureTime() * 1000000.00;
        return true;
    }
    return false;
}

bool CameraPC_Qt6::exposureTimeRange(double &min, double &max, double &us)
{
    qDebug() << "m_pQCamera = " << m_pQCamera;
    if(m_pQCamera)
    {
        qDebug() << m_pQCamera->minimumExposureTime() << ", " << m_pQCamera->maximumExposureTime() << "," << m_pQCamera->exposureTime();
        min = m_pQCamera->minimumExposureTime() * 1000000.00;
        max = m_pQCamera->maximumExposureTime() * 1000000.00;
        us = m_pQCamera->exposureTime() * 1000000.00;
        if(min < 0 || max < 0 || us < 0) return false;
        return true;
    }
    return false;
}

bool CameraPC_Qt6::startGrabbing()
{
    qDebug() << "CameraPC::startGrabbing()";
    if(m_pQCamera)
    {
        qDebug() << "here";
        m_imageCount = 0;
        m_pQCamera->start();

//        setResolution(QSize(1920, 1080));
//        qDebug() << m_pQCamera->supportedViewfinderResolutions();
//        QList<QCameraViewfinderSettings > ViewSets = m_pQCamera->supportedViewfinderSettings();
//        qDebug() << ViewSets.last().resolution();
//        qDebug() << ViewSets.last().pixelFormat();
//        qDebug() << ViewSets.last().maximumFrameRate();
//        m_pQCamera->setViewfinderSettings(ViewSets.last());
        return true;
    }
    return false;
}

bool CameraPC_Qt6::stopGrabbing()
{
    if(m_pQCamera)
    {
        m_pQCamera->stop();
        return true;
    }
    return false;
}

void CameraPC_Qt6::close()
{
    if(m_pQCamera)
    {
        m_pQCamera->stop();
        delete m_pQCamera;
        delete m_surface;
        m_pQCamera = nullptr;
        m_surface = nullptr;
        CameraPCImageProcessing * p = static_cast<CameraPCImageProcessing *>(m_cameraImageProcessing);
        p->m_pQCamera = nullptr;
    }
}

CameraPC_Qt6::~CameraPC_Qt6()
{
    delete m_cameraImageProcessing;
}

bool CameraPCImageProcessing::setSaturation(double value)
{
    if(!m_pQCamera) return false;
    return false;
}

bool CameraPCImageProcessing::whiteBalanceMode(WhiteBalanceMode &mode)
{
    if(!m_pQCamera) return false;
    QCamera::WhiteBalanceMode md = m_pQCamera->whiteBalanceMode();
    if(md == QCamera::WhiteBalanceAuto)
    {
        mode = CameraPCImageProcessing::WhiteBalanceAutoContinuous;
    }
    else
    {
        mode = CameraPCImageProcessing::WhiteBalanceManual;
    }
    return true;
}
bool CameraPCImageProcessing::setWhiteBalanceMode(WhiteBalanceMode mode)
{
    if(!m_pQCamera) return false;
    switch (mode) {
    case Qly::CameraPCImageProcessing::WhiteBalanceManual:
        m_pQCamera->setWhiteBalanceMode(QCamera::WhiteBalanceManual);
        break;
    default:
        m_pQCamera->setWhiteBalanceMode(QCamera::WhiteBalanceAuto);
        break;
    }
    return true;
}

bool CameraPCImageProcessing::setManualWhiteBalance(double colorTemperature, double Tint)
{
    if(!m_pQCamera) return false;
    m_pQCamera->setWhiteBalanceMode(QCamera::WhiteBalanceManual);
    m_pQCamera->setColorTemperature(colorTemperature);
    return true;
}

bool CameraPCImageProcessing::manualWhiteBalance(double &colorTemperature, double &Tint)
{
    if(!m_pQCamera) return false;
    colorTemperature = m_pQCamera->colorTemperature();
    return true;
}

bool CameraPCImageProcessing::saturation(double &value)
{
    if(!m_pQCamera) return false;
    return false;
}

bool CameraPCImageProcessing::saturationEnable(bool &on)
{
    if(!m_pQCamera) return false;
    return false;
}

bool CameraPCImageProcessing::setSaturationEnable(bool on)
{
    if(!m_pQCamera) return false;
    return false;
}

bool CameraPCImageProcessing::setContrast(double value)
{
    if(!m_pQCamera) return false;

    return false;
}

bool CameraPCImageProcessing::contrast(double &value)
{
    if(!m_pQCamera) return false;
    return false;
}

bool CameraPCImageProcessing::contrastEnable(bool &on)
{
    if(!m_pQCamera) return false;
    return false;
}

bool CameraPCImageProcessing::setContrastEnable(bool on)
{
    if(!m_pQCamera) return false;
    return false;
}

bool CameraPCImageProcessing::setDenoise(double value)
{
    if(!m_pQCamera) return false;
    return false;
}

bool CameraPCImageProcessing::denoise(double &value)
{
    if(!m_pQCamera) return false;
    return false;
}

bool CameraPCImageProcessing::denoiseEnable(bool &on)
{
    if(!m_pQCamera) return false;
    return false;
}

bool CameraPCImageProcessing::setDenoiseEnable(bool on)
{
    if(!m_pQCamera) return false;
    return false;
}

bool CameraPCImageProcessing::setBrightness(double value)
{
    if(!m_pQCamera) return false;
    return false;
}

bool CameraPCImageProcessing::brightness(double &value)
{
    if(!m_pQCamera) return false;
    return false;
}

bool CameraPCImageProcessing::setSharpness(double value)
{
    if(!m_pQCamera) return false;
    return false;
}

bool CameraPCImageProcessing::sharpness(double &value)
{
    if(!m_pQCamera) return false;
    return false;
}

bool CameraPCImageProcessing::sharpnessEnable(bool &on)
{
    if(!m_pQCamera) return false;
    return false;
}

bool CameraPCImageProcessing::setSharpnessEnable(bool on)
{
    if(!m_pQCamera) return false;
    return false;
}

} //namespace


